package com.h2cloud.JUCTest.reentrantReadWriteLock;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.StampedLock;

import static com.h2cloud.JUCTest.TimeUtil.Sleeper.sleep;

/**
 * @Package: com.h2cloud.JUCTest.reentrantReadWriteLock
 * @ClassName: StampedLockTest
 * @Author: h2cloud
 * @CreateTime: 2022/6/6 2:45 下午
 * @Description:
 */

/**
 * StampedLock 测试
 * StampedLock 不支持条件变量
 * StampedLock 不支持可重入
 */
public class StampedLockTest {

	public static void main(String[] args) {
		DataContainerStamped dataContainer = new DataContainerStamped(1);
		/**
		 * 可以看到实际没有加读锁
		 */
		// new Thread(() -> {
		// 	dataContainer.read(1);
		// }, "t1").start();
		// sleep(0.5);
		// new Thread(() -> {
		// 	dataContainer.read(0);
		// }, "t2").start();


		new Thread(() -> {
			dataContainer.read(1);
		}, "t1").start();
		sleep(0.5);
		new Thread(() -> {
			dataContainer.write(10);
		}, "t2").start();
	}
}

@Slf4j
class DataContainerStamped {

	private int data;

	final StampedLock lock = new StampedLock();

	public DataContainerStamped(int data) {
		this.data = data;
	}

	public int read(int readTime) {
		long stamp = lock.tryOptimisticRead();
		log.info("optimistic read locking ...{}", stamp);
		sleep(readTime);
		if (lock.validate(stamp)) {
			log.info("read finish... {}", stamp);
			return data;
		}

		// 锁升级 - 读锁
		log.info("update to read lock ...");
		try {
			stamp = lock.readLock();
			log.info("read lock {}", stamp);
			sleep(readTime);
			log.info("read finish ... {}", stamp);
			log.info("read data ... {}", this.data);
			return data;
		} finally {
			lock.unlockRead(stamp);
		}
	}

	public void write(int newData) {
		long stamp = lock.writeLock();
		try {
			log.info("write lock {}", stamp);
			this.data = newData;
			try {
				TimeUnit.SECONDS.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			log.info("write finish ... {}", stamp);
			log.info("write newData ... {}", this.data);
		} finally {
			lock.unlockWrite(stamp);
		}
	}

}
